﻿using Mario.DataFiles;
using Mario.GameEngine;
using Mario.GameEngine.GameSructures;
using Mario.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Mario.UI
{
    public partial class GameWindow : Form
    {
        private string worldNumber;
        private bool goRight = false;
        private bool goLeft = false;
        private bool goUp = true;
        private bool goDown = false;
        private int jumpHeight = 21;
        private int force;
        private int groundHeight = 100;
        private PictureBox player = new PictureBox();
        private GameObjects gameObject;
        private int lifeCount = 3;
        private int score = 0;
        private int timeInterval = 210;
        private bool shouldClose = true;

        /// <summary>
        /// Set the selected world number
        /// </summary>
        /// <param name="worldNumber"></param>
        public GameWindow(string worldNumber)
        {
            InitializeComponent();
            this.worldNumber = worldNumber;
        }

        /// <summary>
        /// On load method
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GameWindow_Load(object sender, EventArgs e)
        {
            String fileName = worldNumber + ".png";
            string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string Filepath = Path.Combine(directory, fileName);
            if (File.Exists(Filepath))
            {
                BackGround.Image = Image.FromFile(Filepath);
            }
            else
            {
                BackGround.Image = CreateImage();
            }


            this.SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, true);
            this.BackColor = System.Drawing.Color.Transparent;
            object O = Resources.Resource1.Small_mario;
            player.BackColor = Color.Transparent;
            player.Image = (Image)O;
            player.Location = new Point(0, 618);
            player.Size = new Size(50, 50);
            BackGround.Controls.Add(player);
            player.BringToFront();
            XMLAccess access = new XMLAccess();
            gameObject = access.GetOBjectsFromXML(worldNumber + ".xml");
            timer1.Start();
            timer2.Start();
        }

        /// <summary>
        /// Create image if noc created before
        /// </summary>
        /// <returns></returns>
        private Image CreateImage()
        {
            ImageCreation imageCreation = new ImageCreation();
            Image createdImage = imageCreation.CreateImage(worldNumber + ".xml");
            createdImage.Save(worldNumber + ".png", System.Drawing.Imaging.ImageFormat.Png);
            return createdImage;
        }

        /// <summary>
        /// Timer tick action
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (goRight)
            {
                player.Location = new Point(player.Location.X + 10, player.Location.Y);
                if (player.Location.X > (gameObject.Castle.XCoordinate + gameObject.Castle.Width / 2))
                {
                    WinGame();
                    timer1.Stop();
                }
                // Bricks detection - Start {
                for (int i = 0; i < gameObject.Bricks.Length; i++)
                {
                    Bricks brick = gameObject.Bricks[i];
                    if (((player.Location.X + player.Size.Width) >= brick.XCoordinate) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)))
                    {
                        player.Location = new Point(brick.XCoordinate - player.Size.Width, player.Location.Y);
                        goRight = false;
                    }
                }
                // Bricks detection - End }

                // BricksB detection - Start {
                for (int i = 0; i < gameObject.BricksB.Length; i++)
                {
                    Bricks brick = gameObject.BricksB[i];
                    if (((player.Location.X + player.Size.Width) >= brick.XCoordinate) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && (player.Location.Y < (brick.YCoordinate + brick.Height)))
                    {
                        player.Location = new Point(brick.XCoordinate - player.Size.Width, player.Location.Y);
                        goRight = false;
                    }
                }
                // BricksB detection - End }

                // BricksQ detection - Start {
                for (int i = 0; i < gameObject.BricksQ.Length; i++)
                {
                    Bricks brick = gameObject.BricksQ[i];
                    if (((player.Location.X + player.Size.Width) >= brick.XCoordinate) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && (player.Location.Y < (brick.YCoordinate + brick.Height)))
                    {
                        player.Location = new Point(brick.XCoordinate - player.Size.Width, player.Location.Y);
                        goRight = false;
                    }
                }
                // BricksQ detection - End }
                if (goRight)
                {
                    goUp = true;
                }
                if ((player.Location.X > 700) && goRight)
                {
                    if (player.Location.X + 700 < BackGround.Size.Width)
                    {
                        BackGround.Location = new Point(BackGround.Location.X - 10, BackGround.Location.Y);
                    }              
                }

           
            }
            if (goLeft)
            {
                player.Location = new Point(player.Location.X - 10, player.Location.Y);
                if (player.Location.X < 0)
                {
                    player.Location = new Point(0, player.Location.Y);

                }
                // Bricks detection - Start {
                for (int i = 0; i < gameObject.Bricks.Length; i++)
                {
                    Bricks brick = gameObject.Bricks[i];
                    if ((brick.XCoordinate < player.Location.X) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate))
                    {
                        player.Location = new Point(brick.XCoordinate + brick.Width, player.Location.Y); 
                        goLeft = false;
                    }
                }
                // Bricks detection - End }

                // BricksB detection - Start {
                for (int i = 0; i < gameObject.BricksB.Length; i++)
                {
                    Bricks brick = gameObject.BricksB[i];
                    if ((brick.XCoordinate < player.Location.X) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.Y < (brick.YCoordinate + brick.Height)))
                    {
                        player.Location = new Point(brick.XCoordinate + brick.Width, player.Location.Y);
                        goLeft = false;
                    }
                }
                // BricksB detection - End }

                // BricksQ detection - Start {
                for (int i = 0; i < gameObject.BricksQ.Length; i++)
                {
                    Bricks brick = gameObject.BricksQ[i];
                    if ((brick.XCoordinate < player.Location.X) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.Y < (brick.YCoordinate + brick.Height)))
                    {
                        player.Location = new Point(brick.XCoordinate + brick.Width, player.Location.Y);
                        goLeft = false;
                    }
                }
                // BricksQ detection - End }

                if ((BackGround.Location.X < 0) && goLeft)
                {
                    BackGround.Location = new Point(BackGround.Location.X + 10, BackGround.Location.Y);
                }

                if (goLeft)
                {
                    goUp = true;
                }
            }
            if (goUp)
            {
                player.Location = new Point(player.Location.X, player.Location.Y - force);
                force--;
                // Bricks detection - Start {
                for (int i = 0; i < gameObject.Bricks.Length; i++)
                {
                    Bricks brick = gameObject.Bricks[i];
                    if (((player.Location.X + player.Size.Width) > brick.XCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate))
                    {
                        player.Location = new Point(player.Location.X, brick.YCoordinate - player.Size.Height);
                        goUp = false;
                    }
                }
                // Bricks detection - End }

                // BricksB detection - Start {
                for (int i = 0; i < gameObject.BricksB.Length; i++)
                {
                    Bricks brick = gameObject.BricksB[i];
                    if (player.Location.Y < (brick.YCoordinate + brick.Width) && ((player.Location.X + player.Size.Width) > brick.XCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > (brick.YCoordinate + brick.Width)))
                    {
                        player.Location = new Point(player.Location.X, brick.YCoordinate + brick.Height);
                        goUp = true;
                        force = 0;
                    }
                    if (((player.Location.X + player.Size.Width) > brick.XCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.Y < (brick.YCoordinate + brick.Height)))
                    {
                        player.Location = new Point(player.Location.X, brick.YCoordinate - player.Size.Height);
                        goUp = false;
                    }

                    
                }
                // BricksB detection - End }

                // BricksQ detection - Start {
                for (int i = 0; i < gameObject.BricksQ.Length; i++)
                {
                    Bricks brick = gameObject.BricksQ[i];
                    if (player.Location.Y < (brick.YCoordinate + brick.Width) && ((player.Location.X + player.Size.Width) > brick.XCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > (brick.YCoordinate + brick.Width)))
                    {
                        player.Location = new Point(player.Location.X, brick.YCoordinate + brick.Height);
                        goUp = true;
                        force = 0;
                        if (brick.value == 1)
                        {
                            brick.value = 0;
                            ChangeQPicture(new Point(brick.XCoordinate, brick.YCoordinate), new Size(brick.Width, brick.Height));
                            ChangeScore(100);

                        }
                    }
                    if (((player.Location.X + player.Size.Width) > brick.XCoordinate) && (player.Location.X < (brick.XCoordinate + brick.Width)) && ((player.Location.Y + player.Size.Height) > brick.YCoordinate) && (player.Location.Y < (brick.YCoordinate + brick.Height)))
                    {
                        player.Location = new Point(player.Location.X, brick.YCoordinate - player.Size.Height);
                        goUp = false;
                    }


                }
                // BricksQ detection - End }
            }

          
         
            if (player.Location.Y + player.Size.Height > this.Height - groundHeight)
            {
                goUp = false;
                player.Location = new Point(player.Location.X, this.Height - groundHeight - player.Size.Height);
            }
            // Water detection - Start {
            if (player.Location.Y + player.Size.Height == this.Height - groundHeight)
            {
                for (int i = 0; i < gameObject.Water.Length ; i++)
                {
                    Bricks waterBrick = gameObject.Water[i];
                    if ((player.Location.X >= waterBrick.XCoordinate) && ((player.Location.X + player.Size.Width) <= (waterBrick.XCoordinate + waterBrick.Width)))
                    {
                        PlayerDied();
                    }
                }
            }
            // Water detection - End }
            if (goDown)
            {

            }
        }

        /// <summary>
        /// Change BrickQ picture if player hit it
        /// </summary>
        /// <param name="location">x and y coordinates</param>
        /// <param name="brickQSize">width and height of brick</param>
        private void ChangeQPicture(Point location, Size brickQSize)
        {
            Graphics g;
            Image backImage = BackGround.Image;
            g = Graphics.FromImage(backImage);

            
            object O2 = Resources.Resource1.UsedBlock;
            Image brick2 = (Image)O2;

            g.DrawImage(brick2, location.X, location.Y, brickQSize.Width, brickQSize.Height);

            BackGround.Image = backImage;
            g.Dispose();
        }

        /// <summary>
        /// On form closed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GameWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (shouldClose)
            {
                foreach (Form form in Application.OpenForms)
                {
                    if (form is MainWindow1)
                    {
                        form.Show();
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Key up action
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GameWindow_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.A)
            {
                goLeft = false;
            }
            if (e.KeyCode == Keys.D)
            {
                goRight = false;
            }
            if (e.KeyCode == Keys.S)
            {
                goDown = false;
            }
        }

        /// <summary>
        /// Change life count
        /// </summary>
        /// <param name="k">value to change lifeCount</param>
        private void ChangeLifeCount(int k)
        {
            lifeCount += k;
            if (lifeCount > 0)
            {
                lifeLabel.Text = "Life : " + lifeCount;
                if (k < 0)
                {
                    LostLife lostView = new LostLife();
                    lostView.Show();
                }
            } else
            {
                LostGame();
            }
           
        }

        /// <summary>
        /// On player death
        /// </summary>
        private void PlayerDied()
        {
            ChangeLifeCount(-1);
            player.Location = new Point(0, BackGround.Size.Height - groundHeight);
            BackGround.Location = new Point(0, BackGround.Location.Y);
            goDown = false;
            goLeft = false;
            goRight = false;
            goUp = false;
        }

        /// <summary>
        /// On game lost
        /// </summary>
        private void LostGame()
        {
            timer1.Stop();
            timer2.Stop();
            TimeSpan result = TimeSpan.FromSeconds(0);
            timeLabel.Text = "Time : " + result.ToString("mm':'ss");
            LostAndWinForm lostForm = new LostAndWinForm(false, score);
            lostForm.Show();
            shouldClose = false;
            this.Close();
         
        }

        /// <summary>
        /// On player won game
        /// </summary>
        private void WinGame()
        {
            timer1.Stop();
            timer2.Stop();
            TimeSpan result = TimeSpan.FromSeconds(0);
            timeLabel.Text = "Time : " + result.ToString("mm':'ss");
            ChangeScore(timeInterval * 10);
            LostAndWinForm winForm = new LostAndWinForm(true, score);
            winForm.Show();
            shouldClose = false;
            this.Close();
        }

        /// <summary>
        /// Change score value
        /// </summary>
        /// <param name="value">Value to change</param>
        private void ChangeScore(int value)
        {
            score += value;
            scoreLabel.Text = "Score : " + score;
        }

        /// <summary>
        /// Key down action
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GameWindow_KeyDown(object sender, KeyEventArgs e)
        {
            if (!goUp)
            {
                if (e.KeyCode == Keys.W)
                {
                    goUp = true;
                    force = jumpHeight;
                }
            }
            if (e.KeyCode == Keys.A)
            {
                goLeft = true;
            }
            if (e.KeyCode == Keys.D)
            {
                goRight = true;
            }
            if (e.KeyCode == Keys.S)
            {
                goDown = true;
            }
        }

        /// <summary>
        /// Timer tick to deal with time of game 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer2_Tick(object sender, EventArgs e)
        {
            timeInterval--;
            if (timeInterval < 0)
            {
                timer1.Stop();
                timer2.Stop();
                LostGame();
            }
            else
            {
                TimeSpan result = TimeSpan.FromSeconds(timeInterval);
                timeLabel.Text = "Time : " + result.ToString("mm':'ss");
            }
        }
    }
}
